using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Globalization;
using System.Security.Cryptography;
using System.Xml;
using CodePlex.Resourceful;
using CodePlex.Resourceful.Amazon.S3;

namespace CodePlex.SpaceBlock
{
    public static class SpaceBlockUtils
    {

        // TODO push down
        public static TValue SafeGet<TKey, TValue>(Dictionary<TKey, TValue> values, TKey key)
        {
            if (!values.ContainsKey(key))
            {
                return default(TValue);
            }
            return values[key];
        }


        public static string Decrypt(string cipherText, string password)
        {
            string[] hex = cipherText.Split('-');
            byte[] cipher = new byte[hex.Length];
            for (int i = 0; i < hex.Length; i++)
            {
                cipher[i] = Byte.Parse(hex[i], NumberStyles.HexNumber);
            }            
            byte[] keyBytes = ProtectedData.Unprotect(cipher, Encoding.Unicode.GetBytes(password), DataProtectionScope.CurrentUser);
            return Encoding.Unicode.GetString(keyBytes);

        }
        public static string Encrypt(string plainText, string password)
        {
            byte[] plainBytes = Encoding.Unicode.GetBytes(plainText);
            byte[] entropyBytes = Encoding.Unicode.GetBytes(password);
            byte[] encryptedBytes = ProtectedData.Protect(plainBytes, entropyBytes, DataProtectionScope.CurrentUser);

            return BitConverter.ToString(encryptedBytes);
        }


        private static readonly List<string> __otherCategories = new List<string>(new string[] { 
            "flv-application"
            
        });

        public static IEnumerable<string> GetContentTypeCategories()
        {
            List<string> rt = new List<string>();

            foreach (string contentType in SpaceBlockUtils.GetContentTypes())
            {
                string category = contentType.Split('/')[0];
                if (!rt.Contains(category) && !__otherCategories.Contains(category))
                {
                    rt.Add(category);
                }
            }

            rt.Add("application/x");
            rt.Add("other");
            rt.Sort();
            return rt.ToArray();
        }

        public static string[] GetContentTypes()
        {
            return SpaceBlockUtils.GetContentTypes(null);
        }


    

        public static string[] GetContentTypes(string category)
        {
            IEnumerable<string> values = MimeMap.List();
            List<string> rt = new List<string>(values);
         
            rt = rt.FindAll(delegate(string item)
            {
                if (category == null)
                {
                    return true;
                }
                if (category.Equals("application",StringComparison.InvariantCultureIgnoreCase))
                {
                    return MonoCompat124.StartsWith(item, category, StringComparison.InvariantCultureIgnoreCase)
                    && !MonoCompat124.StartsWith(item, "application/x-", StringComparison.InvariantCultureIgnoreCase);
                }

                if (category.Equals("other", StringComparison.InvariantCultureIgnoreCase))
                {
                    foreach (string other in __otherCategories)
                    {
                        if (MonoCompat124.StartsWith(item, other + "/", StringComparison.InvariantCultureIgnoreCase))
                        {
                            return true;
                        }
                    }
                    
                }

                return MonoCompat124.StartsWith(item, category, StringComparison.InvariantCultureIgnoreCase);
            });

            // user requested
            if (category == "text")
            {
                rt.Add(MediaType.TextJavascript);
            }


            rt.Sort();
            return rt.ToArray();
        }




        public static NameValuePairs HttpHeaderDescriptions()
        {
            NameValuePairs descriptions = new NameValuePairs();

            descriptions[HttpHeader.AcceptRanges] = "The Accept-Ranges response-header field allows the server to indicate its acceptance of range requests for a resource.";
            descriptions[HttpHeader.ContentRange] = "This indicates the range of bytes returned in the event that you requested a subset of the object by setting the Range request header.";
            descriptions[HttpHeader.ETag] = "The ETag response-header field provides the current value of the entity tag for the requested variant. The entity tag MAY be used for comparison with other entities from the same resource.";
            descriptions[HttpHeader.ContentType] = "The Content-Type entity-header field indicates the media type of the entity-body.";
            descriptions[S3Constants.Headers.Server] = "The Server response-header field contains information about the software used by the origin server to handle the request. The field can contain multiple product tokens (section 3.8) and comments identifying the server and any significant subproducts. The product tokens are listed in order of their significance for identifying the application.";
            descriptions[HttpHeader.LastModified] = "The Last-Modified entity-header field indicates the date and time at which the origin server believes the variant was last modified.";
            descriptions[HttpHeader.Date] = "The Date general-header field represents the date and time at which the message was originated.";
            descriptions[HttpHeader.ContentLength] = "The Content-Length entity-header field indicates the size of the entity-body, in decimal number of OCTETs.";
            descriptions[HttpHeader.TransferEncoding] = "The Transfer-Encoding general-header field indicates what (if any) type of transformation has been applied to the message body in order to safely transfer it between the sender and the recipient. This differs from the content-coding in that the transfer-coding is a property of the message, not of the entity.";


            descriptions[HttpHeader.CacheControl] = "The Cache-Control general-header field is used to specify directives that MUST be obeyed by all caching mechanisms along the request/response chain. The directives specify behavior intended to prevent caches from adversely interfering with the request or response. These directives typically override the default caching algorithms. Cache directives are unidirectional in that the presence of a directive in a request does not imply that the same directive is to be given in the response.";
            descriptions[HttpHeader.ContentMD5] = "The Content-MD5 entity-header field, as defined in RFC 1864 [23], is an MD5 digest of the entity-body for the purpose of providing an end-to-end message integrity check (MIC) of the entity-body. (Note: a MIC is good for detecting accidental modification of the entity-body in transit, but is not proof against malicious attacks.)";
            descriptions[HttpHeader.Vary] = @"The Vary field value indicates the set of request-header fields that fully determines, while the response is fresh, whether a cache is permitted to use the response to reply to a subsequent request without revalidation. For uncacheable or stale responses, the Vary field value advises the user agent about the criteria that were used to select the representation. A Vary field value of "" * "" implies that a cache cannot determine from the request headers of a subsequent request whether this response is the appropriate representation.";
            descriptions[S3Constants.Headers.ContentDisposition] = @"(RFC 2183) If the file's Content-Disposition is set to ""inline"", the file will open in the browser. If Content-Disposition is set to ""attachment"", the browser will open a dialog that asks whether the user wants to open or save the downloaded file. The Content-Disposition header also includes the file name.";


            descriptions[HttpHeader.ContentEncoding] = @"The Content-Encoding entity-header field is used as a modifier to the media-type. When present, its value indicates what additional content codings have been applied to the entity-body, and thus what decoding mechanisms must be applied in order to obtain the media-type referenced by the Content-Type header field. Content-Encoding is primarily used to allow a document to be compressed without losing the identity of its underlying media type.";
            descriptions[HttpHeader.Expires] = @"The Expires entity-header field gives the date/time after which the response is considered stale. A stale cache entry may not normally be returned by a cache (either a proxy cache or a user agent cache) unless it is first validated with the origin server (or with an intermediate cache that has a fresh copy of the entity).  The presence of an Expires field does not imply that the original resource will change or cease to exist at, before, or after that time. The format is an absolute date and time as defined by HTTP-date in section 3.3.1; it MUST be in RFC 1123 date format. HTTP/1.1 clients and caches MUST treat other invalid date formats, especially including the value ""0"", as in the past (i.e., ""already expired"").";

            return descriptions;
        }

    }
}
